home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 1 (Walnut Creek)
/
Aminet - June 1993 [Walnut Creek].iso
/
aminet
/
gfx
/
show
/
mpeg_src_play201.lha
/
amiga
/
amiga.c
next >
Wrap
C/C++ Source or Header
|
1993-02-13
|
20KB
|
1,024 lines
/*
* Implementation of the needed X functions for the Commodore Amiga
*
* Michael Balzer, December 1992
* balzer@heike.informatik.uni-dortmund.de
* bilbo@bagsend.aworld.de
* m.balzer@aworld.(aworld.de|zer|sub.org)
*
* Release 1.0 (8.12.92):
* - First release, needs os3.0, can only display on
* workbench or on 8 bit lores screen
*
* Release 1.22 (11.12.92):
* - Now also runs on system 2.x
* - Uses reqtools.library to ask for the screenmode
* - Version string: 1.22 means Amiga version 2 of mpeg_play 1.2
*
* Release 1.23 (not released due to 2.01):
* - Dither mono & threshold now work (fast!)
* - New option: -saveiff framename_%d.iff (guess for what ;-)
* Saving currently forces screen mode. No support for 24 bit
* yet
* - Added new option: -amiga screen:mode/depth/width/height,
* reworked option dependancies
*
* Release 2.01 (Feb 12 1993):
* - Based upon the new 2.0 release of the mpeg player for UNIX
* - No need to enhance color allocation, as the new player
* allows to set the range values (ncolors = l_rng*cr_rng*cb_rng)
* - 24 Bit IFF save mode implemented
*
* TODO:
* - maybe implement HAM mode
*/
#include <exec/types.h>
#include <exec/memory.h>
#include <exec/libraries.h>
#include <intuition/intuition.h>
#include <intuition/classes.h>
#include <graphics/gfxbase.h>
#include <graphics/gfxmacros.h>
#include <graphics/modeid.h>
#include <graphics/scale.h>
#include <graphics/graphint.h>
#include <dos/dos.h>
#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>
#include <clib/graphics_protos.h>
#include <clib/alib_protos.h>
#include <libraries/reqtools.h>
#include <proto/reqtools.h>
#define static
#define __inline
#include <inline/minreqtools.h>
#undef static
#undef __inline
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <iffp/ilbmapp.h>
#include <stdio.h>
#include <stdlib.h>
#include "video.h"
#ifdef ABS
#undef ABS
#endif
#define ABS(a) (((int)(a)<0) ? -(a) : (a))
char *_version_ = "\0$VER: mpeg_play 2.01 (" __DATE__ ")";
/***********************************************************/
extern
struct Library *SysBase;
struct IntuitionBase *IntuitionBase = NULL;
struct GfxBase *GfxBase = NULL;
struct Library *IFFParseBase = NULL;
struct ReqToolsBase *ReqToolsBase = NULL;
struct Screen *mpeg_screen = NULL;
struct Window *mpeg_window = NULL;
struct RastPort *rp = NULL;
struct RastPort *temprp = NULL;
struct BitMap *tempbm = NULL;
struct BitMap *bwbm = NULL;
struct ViewPort *vp = NULL;
char *amiga_option = "";
int offx, offy;
struct ColorMap *cm = NULL;
int used_colors[ 256 ];
int used_cnt = 0;
UWORD saved_colors[ 256 ];
int saved_cnt = 0;
int rev3;
char *saveiff_option = "";
int saveFlag = 0;
extern int loopFlag;
struct ILBMInfo *ilbm = 0;
extern int ditherType;
unsigned char *rsrc = 0, *gsrc = 0, *bsrc = 0;
struct BitMap *bm24 = 0, *rbm = 0, *gbm = 0, *bbm = 0;
struct RastPort *rrp = 0, *grp = 0, *brp = 0;
struct RastPort *rtemprp = 0, *gtemprp = 0, *btemprp = 0;
int real_width, real_height;
/***********************************************************/
/* support routines for os revision 2 */
struct BitMap *myAllocBitMap( unsigned long sizex, unsigned long sizey,
unsigned long depth, unsigned long flags,
struct BitMap *friend_bitmap )
{
struct BitMap *bm;
unsigned long extra;
extra = (depth > 8) ? depth - 8 : 0;
bm = AllocVec( sizeof *bm + (extra * 4), MEMF_CLEAR );
if( bm )
{
int i;
InitBitMap( bm, depth, sizex, sizey );
for( i=0; i<depth; i++ )
{
if( !(bm->Planes[i] = AllocRaster(sizex, sizey)) )
{
while( i-- ) FreeRaster( bm->Planes[i], sizex, sizey );
FreeVec( bm );
bm = 0;
break;
}
}
}
return bm;
}
void myFreeBitMap( struct BitMap *bm )
{
while( bm->Depth-- )
FreeRaster( bm->Planes[bm->Depth], bm->BytesPerRow*8, bm->Rows );
FreeVec( bm );
}
LONG myObtainBestPenA( struct ColorMap *cm, unsigned long r, unsigned long g,
unsigned long b, struct TagItem *tags )
{
int i, best, err, besterr;
int br, bg, bb;
int colors;
/* Farbwerte auf 4 Bit bringen */
r >>= 28; g >>= 28; b >>= 28;
/* Strategie: Zunächst die Farbe suchen, die der gewünschten
* am nächsten liegt. Wenn Farbe >= 4, Farbe auf Mittelwert zw.
* aktuellen und gesuchten Werten setzen und zurückgeben.
* Die unteren vier bleiben unverändert (Workbench).
*/
best = 0;
besterr = 100;
colors = 1 << rp->BitMap->Depth;
for( i=0; i<colors; i++ )
{
long rgb = GetRGB4( cm, i );
int cr, cg, cb;
cr = rgb >> 8 & 15;
cg = rgb >> 4 & 15;
cb = rgb & 15;
err = ABS( r - cr )
+ ABS( g - cg )
+ ABS( b - cb );
if( err < besterr )
{
best = i;
besterr = err;
br = cr;
bg = cg;
bb = cb;
}
}
if( best >= 4 && besterr != 0 )
{
/* Farbe anpassen */
SetRGB4( vp, best,
(r + br) / 2,
(g + bg) / 2,
(b + bb) / 2 );
}
return best;
}
void myReleasePen( struct ColorMap *cm, unsigned long n )
{
/* Farbe restaurieren */
long rgb = saved_colors[n];
int cr, cg, cb;
cr = rgb >> 8 & 15;
cg = rgb >> 4 & 15;
cb = rgb & 15;
SetRGB4( vp, n, cr, cg, cb );
}
/***********************************************************/
void FreeTempRP( struct RastPort *rp )
{
if( rp )
{
if( rp->BitMap )
{
if( rev3 ) FreeBitMap( rp->BitMap );
else myFreeBitMap( rp->BitMap );
}
FreeVec( rp );
}
}
struct RastPort *MakeTempRP( struct RastPort *org )
{
struct RastPort *rp;
if( rp = AllocVec(sizeof *rp, MEMF_ANY) )
{
memcpy( rp, org, sizeof *rp );
rp->Layer = NULL;
if( rev3 )
rp->BitMap = AllocBitMap( org->BitMap->BytesPerRow * 8, 1,
org->BitMap->Depth, NULL, org->BitMap );
else
rp->BitMap = myAllocBitMap( org->BitMap->BytesPerRow * 8, 1,
org->BitMap->Depth, NULL, org->BitMap );
if( !rp->BitMap )
{
FreeVec( rp );
rp = NULL;
}
}
return rp;
}
void amiga_closedown( void )
{
if( cm )
{
while( used_cnt-- )
if( rev3 ) ReleasePen( cm, used_colors[used_cnt] );
else myReleasePen( cm, used_colors[used_cnt] );
}
if( mpeg_window ) CloseWindow( mpeg_window );
if( mpeg_screen ) CloseScreen( mpeg_screen );
FreeTempRP( temprp );
if( bwbm )
{
if( rev3 ) FreeBitMap( bwbm );
else myFreeBitMap( bwbm );
}
if( ilbm )
{
if( ilbm->ParseInfo.iff )
FreeIFF( ilbm->ParseInfo.iff );
FreeVec( ilbm );
}
if( rsrc ) FreeVec( rsrc );
if( gsrc ) FreeVec( gsrc );
if( bsrc ) FreeVec( bsrc );
if( bm24 ) myFreeBitMap( bm24 );
if( rbm ) { rbm->Depth = 0; myFreeBitMap( rbm ); }
if( gbm ) { gbm->Depth = 0; myFreeBitMap( gbm ); }
if( bbm ) { bbm->Depth = 0; myFreeBitMap( bbm ); }
if( rrp ) FreeVec( rrp );
if( grp ) FreeVec( grp );
if( brp ) FreeVec( brp );
FreeTempRP( rtemprp );
FreeTempRP( gtemprp );
FreeTempRP( btemprp );
if( ReqToolsBase ) CloseLibrary( (struct Library *) ReqToolsBase );
if( IFFParseBase ) CloseLibrary( (struct Library *) IFFParseBase );
if( GfxBase ) CloseLibrary( (struct Library *) GfxBase );
if( IntuitionBase ) CloseLibrary( (struct Library *) IntuitionBase );
}
void open_display( void )
{
struct rtScreenModeRequester *scrmodereq;
static struct TagItem windowtags[] =
{
{ WA_PubScreen, NULL },
{ WA_Left, 32 },
{ WA_Top, 32 },
{ WA_Width, 160 },
{ WA_Height, 120 },
{ WA_Title, (ULONG) "MPEG Window" },
{ WA_IDCMP, IDCMP_CLOSEWINDOW },
{ WA_Flags, WFLG_DRAGBAR | WFLG_DEPTHGADGET | WFLG_CLOSEGADGET | WFLG_NOCAREREFRESH | WFLG_ACTIVATE | WFLG_RMBTRAP },
{ WA_ScreenTitle, (ULONG) "MPEG Player V2.01, Amiga version by Michael Balzer 2/93" },
{ TAG_END }
};
if( strcmp(amiga_option, "window") == 0 )
{
/* try to open a window */
struct Screen *s;
if( s = LockPubScreen(NULL) )
{
windowtags[0].ti_Data = (ULONG) s;
mpeg_window = OpenWindowTagList( NULL, windowtags );
if( mpeg_window )
{
rp = mpeg_window->RPort;
offx = mpeg_window->BorderLeft;
offy = mpeg_window->BorderTop;
}
UnlockPubScreen( NULL, s );
}
}
/* fallback to own screen */
if( !mpeg_window )
{
BOOL ok;
ULONG id=0, width=320, height=200, depth=8, oscan=0;
if( strncmp(amiga_option, "screen", 6) == 0 )
{
char *s = strtok( amiga_option, ":/" );
int i;
for( i=0; s; s=strtok(NULL, ":/") )
{
switch( i++ )
{
case 0:
/* discard first one */
break;
case 1:
if( *s )
id = strtol( s, NULL, 0 );
break;
case 2:
if( *s )
depth = atoi( s );
break;
case 3:
if( *s )
width = atol( s );
break;
case 4:
if( *s )
height = atol( s );
break;
}
}
ok = TRUE;
}
else
{
if( scrmodereq = rtAllocRequestA( RT_SCREENMODEREQ, NULL ) )
{
ok = rtScreenModeRequest( scrmodereq,
"MPEG: Pick a screen mode",
RTSC_Flags, SCREQF_DEPTHGAD|SCREQF_SIZEGADS|SCREQF_OVERSCANGAD,
TAG_END );
rtFreeRequest( scrmodereq );
id = scrmodereq->DisplayID;
width = scrmodereq->DisplayWidth;
height = scrmodereq->DisplayHeight;
depth = scrmodereq->DisplayDepth;
oscan = scrmodereq->OverscanType;
if( ok )
printf( " -amiga screen:0x%lx/%d/%d/%d\n",
id, depth, width, height );
}
else
ok = FALSE;
}
if( ok )
{
mpeg_screen = OpenScreenTags( NULL,
SA_Title, (ULONG) "MPEG Screen",
SA_DisplayID, id,
SA_Width, width,
SA_Height, height,
SA_Depth, depth,
SA_Overscan, oscan,
SA_Quiet, TRUE,
SA_SharePens, TRUE,
TAG_END );
/* SA_AutoScroll, scrmodereq->AutoScroll, */
/* Autoscroll would need a backdrop window, but that
* would posssibly slow it down even more...
*/
}
if( mpeg_screen )
rp = &mpeg_screen->RastPort;
offx = offy = 0;
}
}
Display *XOpenDisplay( _Xconst char *display_name )
{
int y;
if( !IntuitionBase )
{
/* install closedown routine */
atexit( amiga_closedown );
/* open shared libraries */
IntuitionBase = (struct IntuitionBase *) OpenLibrary( "intuition.library", 0 );
if( !IntuitionBase ) return NULL;
GfxBase = (struct GfxBase *) OpenLibrary( "graphics.library", 0 );
if( !GfxBase ) return NULL;
IFFParseBase = OpenLibrary( "iffparse.library", 0 );
if( !IFFParseBase ) return NULL;
ReqToolsBase = (struct ReqToolsBase *) OpenLibrary( "reqtools.library", 38 );
if( !ReqToolsBase )
{
puts( "I need reqtools.library v38!\n" );
return NULL;
}
rev3 = (GfxBase->LibNode.lib_Version >= 39);
}
/* Save option enabled? */
if( *saveiff_option )
{
saveFlag = 1;
loopFlag = 0; /* don't loop while saving */
if( !(ilbm = (struct ILBMInfo *) AllocVec( sizeof *ilbm, MEMF_CLEAR )) )
{
puts( "out of mem" );
return NULL;
}
if( !(ilbm->ParseInfo.iff = AllocIFF()) )
{
puts( "no iff handle" );
return NULL;
}
/* iffp routines need screen for saving */
if( strcmp( amiga_option, "window" ) == 0 )
amiga_option = "";
}
if( ditherType == FULL_COLOR_DITHER )
{
if( !saveFlag )
return (Display *) 0;
}
else
{
/* open some display */
open_display();
if( !mpeg_window && !mpeg_screen )
return NULL;
/* Viewport und Colormap bestimmen */
vp = (mpeg_screen)
? &mpeg_screen->ViewPort
: &mpeg_window->WScreen->ViewPort;
cm = vp -> ColorMap;
/* Farben sichern */
saved_cnt = 1 << rp->BitMap->Depth;
for( y=0; y<saved_cnt; y++ )
saved_colors[y] = GetRGB4( cm, y );
/* temporären Rastport aufsetzen */
temprp = MakeTempRP( rp );
if( !temprp )
{
puts( "out of memory!" );
exit( 20 );
}
}
return (Display *) 1;
}
int XDefaultScreen( Display *display )
{
return 1;
}
XFlush( Display *display )
{
}
/***************************************************************/
Window XRootWindow(
Display* display,
int screen_number )
{
return 1;
}
Window XCreateSimpleWindow(
Display* display,
Window parent,
int x,
int y,
unsigned int width,
unsigned int height,
unsigned int border_width,
unsigned long border,
unsigned long background )
{
return (Window) 1;
}
Window XCreateWindow(
Display* display,
Window parent,
int x,
int y,
unsigned int width,
unsigned int height,
unsigned int border_width,
int depth,
unsigned int class,
Visual* visual,
unsigned long valuemask,
XSetWindowAttributes* attributes )
{
/* Generiert Fenster auf Full-Color-Display */
/* für's Frame-Speichern sinnvoll,
* dafür wird aber kein echter Output gemacht,
* sondern nur direkt gespeichert.
*/
return (Window) 1;
}
XSetStandardProperties(
Display* display,
Window w,
_Xconst char* window_name,
_Xconst char* icon_name,
Pixmap icon_pixmap,
char** argv,
int argc,
XSizeHints* hints )
{
}
XMapWindow(
Display* display,
Window w )
{
}
XResizeWindow(
Display* display,
Window w,
unsigned int width,
unsigned int height )
{
printf( "Anim size: %d x %d\n", width, height );
/* für später... */
real_width = width;
real_height = height;
if( mpeg_screen ) return;
if( mpeg_window )
ChangeWindowBox( mpeg_window,
mpeg_window->LeftEdge, mpeg_window->TopEdge,
width + mpeg_window->BorderLeft + mpeg_window->BorderRight,
height + mpeg_window->BorderTop + mpeg_window->BorderBottom );
}
/***************************************************************/
Status XMatchVisualInfo(
Display* display,
int screen,
int depth,
int class,
XVisualInfo* vinfo_return )
{
return( depth <= 8 );
}
XVisualInfo *XGetVisualInfo(
Display* display,
long vinfo_mask,
XVisualInfo* vinfo_template,
int* nitems_return )
{
*nitems_return = 0;
return vinfo_template;
}
GC XCreateGC(
Display* display,
Drawable d,
unsigned long valuemask,
XGCValues* values )
{
return (GC) 1;
}
/***************************************************************/
XImage *XCreateImage(
Display* display,
Visual* visual,
unsigned int depth,
int format,
int offset,
char* data,
unsigned int width,
unsigned int height,
int bitmap_pad,
int bytes_per_line )
{
XImage *xi;
/* Höhenkorrektur */
width = real_width;
height = real_height;
if( xi = calloc(sizeof *xi, 1) )
{
xi->width = width;
xi->height = height;
xi->depth = depth;
xi->f.destroy_image = (int (*)()) free;
if( depth == 1 )
{
/* BitMap im ChipMem allokieren */
if( rev3 )
bwbm = AllocBitMap( width, height, 1, NULL, rp->BitMap );
else
bwbm = myAllocBitMap( width, height, 1, NULL, rp->BitMap );
if( !bwbm )
{
puts( "XCreateImage: Out of memory!" );
exit( 20 );
}
}
else if( depth >= 24 )
{
/* Save-BitMap anlegen */
int i;
/* R, G und B-Bereich für WPA8 */
rsrc = AllocVec( width * height, MEMF_ANY );
gsrc = AllocVec( width * height, MEMF_ANY );
bsrc = AllocVec( width * height, MEMF_ANY );
if( !rsrc || !gsrc || !bsrc )
{
puts( "XCreateImage: Out of memory!" );
exit( 20 );
}
/* 24-Bit-BitMap */
bm24 = myAllocBitMap( width, height, 24, NULL, NULL );
if( !bm24 )
{
puts( "XCreateImage: Out of memory!" );
exit( 20 );
}
/* 8-Bit-BitMaps */
rbm = myAllocBitMap( width, height, 0, NULL, NULL );
gbm = myAllocBitMap( width, height, 0, NULL, NULL );
bbm = myAllocBitMap( width, height, 0, NULL, NULL );
if( !rbm || !gbm || !bbm )
{
puts( "XCreateImage: Out of memory!" );
exit( 20 );
}
rbm->Depth = 8;
for( i=0; i<8; i++ ) rbm->Planes[i] = bm24->Planes[i];
gbm->Depth = 8;
for( i=0; i<8; i++ ) gbm->Planes[i] = bm24->Planes[8+i];
bbm->Depth = 8;
for( i=0; i<8; i++ ) bbm->Planes[i] = bm24->Planes[16+i];
/* 8-Bit-RastPorts */
rrp = AllocVec( sizeof *rrp, MEMF_ANY );
grp = AllocVec( sizeof *grp, MEMF_ANY );
brp = AllocVec( sizeof *brp, MEMF_ANY );
if( !rrp || !grp || !brp )
{
puts( "XCreateImage: Out of memory!" );
exit( 20 );
}
InitRastPort( rrp );
InitRastPort( grp );
InitRastPort( brp );
rrp->BitMap = rbm;
grp->BitMap = gbm;
brp->BitMap = bbm;
rtemprp = MakeTempRP( rrp );
gtemprp = MakeTempRP( grp );
btemprp = MakeTempRP( brp );
if( !rtemprp || !gtemprp || !btemprp )
{
puts( "XCreateImage: Out of memory!" );
exit( 20 );
}
}
}
return xi;
}
XPutImage(
Display* display,
Drawable d,
GC gc,
XImage* image,
int src_x,
int src_y,
int dest_x,
int dest_y,
unsigned int width,
unsigned int height )
{
struct IntuiMessage *imsg;
ULONG class;
/* in image->data ist das Bild als Folge von Bytes,
* display zeigt auf nix,
* d und gc sind egal,
* src_? und dest_? sind hier immer 0,
* width und height stimmen mit den Bilddimensionen überein
* (oder sollten zumindest...)
*/
if( image->depth == 1 )
{
/* B&W Bitmap (1 Bit = 1 Pixel) */
/* erst ins ChipMem kopieren */
CopyMem( image->data, bwbm->Planes[0], bwbm->BytesPerRow * bwbm->Rows );
/* und dann anzeigen */
BltBitMapRastPort( bwbm, 0, 0, rp, offx, offy, width, height, 0x030 );
}
else if( image->depth == 8 )
{
/* Standard 8 Bit Bitmap (chunky pixels) */
WritePixelArray8( rp, offx, offy, offx+width-1, offy+height-1, image->data, temprp );
}
else if( image->depth >= 24 )
{
/* ham not yet implemented */
}
/* CloseGadget abfragen */
if( mpeg_window )
{
while( imsg = (struct IntuiMessage *) GetMsg(mpeg_window->UserPort) )
{
class = imsg->Class;
ReplyMsg( (struct Message *) imsg );
if( class == CLOSEWINDOW )
exit( 0 );
}
}
/* Bild abspeichern */
if( saveFlag )
{
static long frame = 0;
static char framename[ 256 ];
sprintf( framename, saveiff_option, frame++ );
if( image->depth <= 8 )
{
/* Palettenmodus */
int w = rp->BitMap->BytesPerRow * 8,
h = rp->BitMap->Rows;
int cc = 1 << rp->BitMap->Depth;
if( rev3 )
{
ULONG colortable[256 * 3];
GetRGB32( cm, 0, cc, colortable );
saveilbm( ilbm, rp->BitMap, GetVPModeID(vp),
w, h, w, h, colortable, cc, 32,
mskNone, 0, NULL, NULL, framename );
}
else
{
UWORD colortable[256];
int i;
for( i=0; i<cc; i++ )
colortable[i] = GetRGB4( cm, i );
saveilbm( ilbm, rp->BitMap, GetVPModeID(vp),
w, h, w, h, colortable, cc, 4,
mskNone, 0, NULL, NULL, framename );
}
}
else
{
/* True-Color */
/* R, G und B-Arrays füllen */
{
unsigned char *i = image->data, *rp, *gp, *bp;
long c = width * height;
rp = rsrc;
gp = gsrc;
bp = bsrc;
while( c-- )
{
i++;
*bp++ = *i++;
*gp++ = *i++;
*rp++ = *i++;
}
}
/* Konvertieren */
{
WritePixelArray8( rrp, 0, 0, width-1, height-1, rsrc, rtemprp );
WritePixelArray8( grp, 0, 0, width-1, height-1, gsrc, gtemprp );
WritePixelArray8( brp, 0, 0, width-1, height-1, bsrc, btemprp );
}
/* Speichern */
{
int w = bm24->BytesPerRow * 8,
h = bm24->Rows;
saveilbm( ilbm, bm24, 0,
w, h, w, h, NULL, 0, 0,
mskNone, 0, NULL, NULL, framename );
}
}
}
}
/***************************************************************/
Colormap XCreateColormap(
Display* display,
Window w,
Visual* visual,
int alloc )
{
return 1;
}
Colormap XDefaultColormap(
Display* display,
int screen_number )
{
return 1;
}
Status XAllocColor(
Display* display,
Colormap colormap,
XColor* xcolor )
{
long color;
if( rev3 )
color = ObtainBestPenA( cm,
xcolor->red << 16, xcolor->green << 16, xcolor->blue << 16,
NULL );
else
color = myObtainBestPenA( cm,
xcolor->red << 16, xcolor->green << 16, xcolor->blue << 16,
NULL );
used_colors[ used_cnt++ ] = color;
xcolor->pixel = color;
return color;
}
/***************************************************************/
XFree( void *data )
{
}